home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 015 / bawk2a.arc / BAWKACT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1986-07-27  |  8.0 KB  |  396 lines

  1. /*
  2.  * Bawk C actions compiler
  3.  */
  4. #include <stdio.h>
  5.  
  6. #include "bawk.h"
  7.  
  8. act_compile( actbuf )
  9. char *actbuf;               /* where tokenized actions are compiled into */
  10. {    
  11.     Where = ACTION;
  12.     return stmt_compile( actbuf );
  13.     }
  14.  
  15. pat_compile( actbuf )
  16. char *actbuf;              /* where tokenized actions are compiled into */
  17. {    
  18.     Where = PATTERN;
  19.     return stmt_compile( actbuf );
  20.     }
  21.  
  22. stmt_compile( actbuf )
  23. char *actbuf;             /* where tokenized actions are compiled into */
  24. {    
  25. /*
  26.  * Read and tokenize C actions from current input file into the
  27.  * action buffer.  Strip out comments and whitespace in the
  28.  * process.
  29.  */
  30.    void storeptr();
  31.     char *actptr,           /* actbuf pointer */
  32.         *cp,               /* work pointer */
  33.           buf[MAXLINELEN];   /* string buffer */
  34.     int  braces,            /* counts '{}' pairs - return when 0 */
  35.          parens,            /* counts '()' pairs */
  36.          i,                 /* temp */
  37.          c;                 /* current input character */
  38.  
  39.     braces = parens = 0;
  40.     actptr = actbuf;
  41.     while ( (c = getcharacter()) != -1 )
  42.     {    
  43. /*
  44.  * Skip over spaces, tabs and newlines
  45.  */
  46.         if ( c==' ' || c=='\t' || c=='\n' ) continue;
  47.         if ( c=='#' ) {
  48. /*
  49.  * Skip comments.  Comments start with a '#' and
  50.  * end at the next newline.
  51.  */
  52.             while ( (c = getcharacter()) != -1 && c!='\n' )
  53.                 ;
  54.             continue;
  55.             }
  56.  
  57.         if ( c=='{' ) {
  58.             if ( Where==PATTERN ) {
  59. /*
  60.  * We're compiling a pattern. The '{' marks
  61.  * the beginning of an action statement.
  62.  * Push the character back and return.
  63.  */
  64.                 ungetcharacter( '{' );
  65.                 break;
  66.                 }
  67.             else {    
  68. /*
  69.  * We must be compiling an action statement.
  70.  * '{'s mark beginning of action or compound
  71.  * statements.
  72.  */
  73.                 ++braces;
  74.                 *actptr++ = T_LBRACE;
  75.                 }
  76.             }
  77.         else if ( c=='}' ) {
  78.             *actptr++ = T_RBRACE;
  79.             if ( ! --braces )
  80. /*
  81.  * Found the end of the action string
  82.  */
  83.                 break;
  84.             }
  85.         else if ( c=='(' ) {
  86.             ++parens;
  87.             *actptr++ = T_LPAREN;
  88.             }
  89.         else if ( c==')' ) {
  90.             if ( --parens < 0 ) error( "mismatched '()'", ACT_ERROR );
  91.             *actptr++ = T_RPAREN;
  92.             }
  93.         else if ( c==',' && !braces && !parens && Where==PATTERN ) {
  94. /*
  95.  * found a comma outside of any braces or parens-
  96.  * this must be a regular expression seperator.
  97.  */
  98.             ungetcharacter( ',' );
  99.             break;
  100.             }
  101. /*
  102.  * Check if it's a regular expression:
  103.  */
  104.         else if ( c=='/' ) {
  105. /*
  106.  * A '/' inside a pattern string starts a regular expression.  Inside
  107.  * action strings, a '/' is the division operator.
  108.  */
  109.             if ( Where == PATTERN ) goto dopattern;
  110.             else *actptr++ = T_DIV;
  111.             }
  112.         else if ( c=='@' ) {
  113. dopattern:
  114. /*
  115.  * Within action strings, only the '@' may be used to delimit regular
  116.  * expressions
  117.  */
  118.             *actptr++ = T_REGEXP;
  119.             ungetcharacter( c );
  120.             actptr += re_compile( actptr );
  121.             }
  122. /*
  123.  * symbol, string or constant:
  124.  */
  125.         else if ( alpha( c ) ) {
  126. /*
  127.  * It's a symbol reference. Copy the symbol into string buffer.
  128.  */
  129.             cp = buf;
  130.             do
  131.                 *cp++ = c;
  132.             while ( (c=getcharacter()) != -1 && alphanum( c ) );
  133.             ungetcharacter( c );
  134.             *cp = 0;
  135. /*
  136.  * Check if a keyword, builtin function or variable.
  137.  */
  138.             if (( c = iskeyword( buf ) ) != 0) *actptr++ = c;
  139.             else if (( i = isfunction( buf ) ) != 0) {
  140.                 *actptr++ = T_FUNCTION;
  141.                 storeint( actptr, i );
  142.                 actptr += sizeof( i );
  143.                 }
  144.             else {    
  145. /*
  146.  * It's a symbol name.
  147.  */
  148.                 *actptr++ = T_VARIABLE;
  149.                 if ( (cp = (char *) findvar( buf )) == 0 )
  150.                     cp = (char *) addvar( buf );
  151.                 storeptr( actptr, cp );
  152.                 actptr += sizeof( cp );
  153.                 }
  154.             }
  155.         else if ( c == '"' ) {
  156. /*
  157.  * It's a string constant
  158.  */
  159.             *actptr++ = T_STRING;
  160.             actptr = str_compile( actptr, '"' );
  161.             }
  162.         else if ( c == '\'' ) {
  163. /*
  164.  * It's a character constant
  165.  */
  166.             *actptr++ = T_CONSTANT;
  167.             str_compile( buf, '\'' );
  168.             storeint( actptr, *buf );
  169.             actptr += sizeof( i );
  170.             }
  171.         else if ( num( c ) ) {
  172. /*
  173.  * It's a numeric constant
  174.  */
  175.             *actptr++ = T_CONSTANT;
  176.             cp = buf;
  177.             do
  178.                 *cp++ = c;
  179.             while ( (c=getcharacter()) != -1 && num(c) );
  180.             ungetcharacter( c );
  181.             *cp = 0;
  182.             storeint( actptr, atoi( buf ) );
  183.             actptr += sizeof( i );
  184.             }
  185. /*
  186.  * unary operator:
  187.  */
  188.         else if ( c == '$' ) *actptr++ = T_DOLLAR;
  189. /*
  190.  * or binary operator:
  191.  */
  192.         else if ( c == '=' ) {
  193.             if ( (c=getcharacter()) == '=' ) *actptr++ = T_EQ;
  194.             else {    
  195.                 ungetcharacter( c );
  196.                 *actptr++ = T_ASSIGN;
  197.                 }
  198.             }
  199.         else if ( c == '!' ) {
  200.             if ( (c=getcharacter()) == '=' ) *actptr++ = T_NE;
  201.             else {    
  202.                 ungetcharacter( c );
  203.                 *actptr++ = T_LNOT;
  204.                 }
  205.             }
  206.  
  207.         else if ( c == '<' ) {
  208.             if ( (c=getcharacter()) == '<' ) *actptr++ = T_SHL;
  209.             else if ( c == '=' )    *actptr++ = T_LE;
  210.             else {    
  211.                 ungetcharacter( c );
  212.                 *actptr++ = T_LT;
  213.                 }
  214.             }
  215.  
  216.         else if ( c == '>' ) {
  217.             if ( (c=getcharacter()) == '>' ) *actptr++ = T_SHR;
  218.             else if ( c == '=' ) *actptr++ = T_GE;
  219.             else {    
  220.                 ungetcharacter( c );
  221.                 *actptr++ = T_GT;
  222.                 }
  223.             }
  224.  
  225.         else if ( c == '&' ) {
  226.             if ( (c=getcharacter()) == '&' ) *actptr++ = T_LAND;
  227.             else {    
  228.                 ungetcharacter( c );
  229.                 *actptr++ = T_AND;
  230.                 }
  231.             }
  232.  
  233.         else if ( c == '|' ) {
  234.             if ( (c=getcharacter()) == '|' ) *actptr++ = T_LIOR;
  235.             else {    
  236.                 ungetcharacter( c );
  237.                 *actptr++ = T_IOR;
  238.                 }
  239.             }
  240.         else if ( c == '+' ) {
  241.             if ( (c=getcharacter()) == '+' ) *actptr++ = T_INCR;
  242.             else {    
  243.                 ungetcharacter( c );
  244.                 *actptr++ = T_ADD;
  245.                 }
  246.             }
  247.  
  248.         else if ( c == '-' ) {
  249.             if ( (c=getcharacter()) == '-' ) *actptr++ = T_DECR;
  250.             else {    
  251.                 ungetcharacter( c );
  252.                 *actptr++ = T_SUB;
  253.                 }
  254.             }
  255.  
  256. /*
  257.  * punctuation
  258.  */
  259.         else if ( instr( c, "[](),;*/%+-^~" ) ) *actptr++ = c;
  260.  
  261.         else {    
  262. /*
  263.  * Bad character in input line
  264.  */
  265.             error( "lexical error", ACT_ERROR );
  266.             }
  267.  
  268.         if ( actptr >= Workbuf + MAXWORKBUFLEN )
  269.             error( "action too long", MEM_ERROR );
  270.         }
  271.     if ( braces || parens )
  272.         error( "mismatched '{}' or '()'", ACT_ERROR );
  273.  
  274.     *actptr++ = T_EOF;
  275.  
  276.     return actptr - actbuf;
  277.     }
  278.  
  279. char *
  280. str_compile( str, delim )
  281. char *str, delim;
  282. {    
  283. /*
  284.  * Compile a string from current input file into the given string buffer.
  285.  * Stop when input character is the delimiter in "delim".  Returns a
  286.  * pointer to the first character after the string.
  287.  */
  288.     int c;
  289.     char buf[ MAXLINELEN ];
  290.  
  291.     while ( (c = getcharacter()) != -1 && c != delim) {
  292.         if ( c == '\\' ) {
  293.             switch ( c = getcharacter() ) {
  294.                case -1:
  295.                    goto err;
  296.                case 'b':
  297.                    c = '\b'; 
  298.                    break;
  299.                case 'n':
  300.                    c = '\n'; 
  301.                    break;
  302.                case 't':
  303.                    c = '\t'; 
  304.                    break;
  305.                case 'f':
  306.                    c = '\f'; 
  307.                    break;
  308.                case 'r':
  309.                    c = '\r'; 
  310.                    break;
  311.                case '0':
  312.                case '1':
  313.                case '2':
  314.                case '3':
  315.                    *buf = c;
  316.                    for ( c=1; c<3; ++c ) {
  317.                        if ( (buf[c]=getcharacter()) == -1 ) goto err;
  318.                        }
  319.                    buf[c] = 0;
  320.                    sscanf( buf, "%o", &c );
  321.                    break;
  322.                case '\n':
  323.                    if ( getcharacter() == -1 ) goto err;
  324.                default:
  325.                    if ( (c = getcharacter()) == -1 ) goto err;
  326.                 }
  327.             }
  328.         *str++ = c;
  329.         }
  330.     *str++ = 0;
  331.  
  332.     return str;
  333. err:
  334.     sprintf( buf, "missing %c delimiter", delim );
  335.     error( buf, 4 );
  336.     }
  337.  
  338. storeint( ip, i )
  339. int *ip, i;
  340. {    
  341.     return *ip = i;
  342.     }
  343. void
  344. storeptr( pp, p )
  345. char **pp, *p;
  346. {    
  347.     *pp = p;
  348.     }
  349.  
  350. fetchint( ip )
  351. int *ip;
  352. {    
  353.     return *ip;
  354.     }
  355.  
  356. char *
  357. fetchptr( pp )
  358. char **pp;
  359. {    
  360.     return *pp;
  361.     }
  362.  
  363. getoken() {    
  364.     char *cp;
  365.     int i;
  366.  
  367.     switch ( Token = *Actptr++ ) {
  368.        case T_STRING:
  369.        case T_REGEXP:
  370.            Value.dptr = Actptr;
  371.            Actptr += strlen( Actptr ) + 1;
  372.            break;
  373.        case T_VARIABLE:
  374.            Value.dptr = fetchptr( Actptr );
  375.            Actptr += sizeof( cp );
  376.            break;
  377.        case T_FUNCTION:
  378.        case T_CONSTANT:
  379.            Value.ival = fetchint( Actptr );
  380.            Actptr += sizeof( i );
  381.            break;
  382.        case T_EOF:
  383.            --Actptr;
  384.        default:
  385.            Value.dptr = 0;
  386.         }
  387.  
  388. #ifdef DEBUG
  389.     if ( Debug > 1 )
  390.         printf( "Token='%c' (0x%x), Value=%d\n",
  391.         Token,Token,Value.ival );
  392. #endif
  393.  
  394.     return Token;
  395.     }
  396.